/*
 * GraphQL启动配置 - GraphQL模块的启动配置
 * 
 * 主要功能：
 * - 配置GraphQL相关的服务注册
 * - 添加自定义内容部件的GraphQL支持
 * - 注册GraphQL过滤器和构建器
 * - 提供GraphQL schema的扩展机制
 */

using Lombiq.TrainingDemo.GraphQL.Services;
using Lombiq.TrainingDemo.Models;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Apis;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.GraphQL.Queries;
using OrchardCore.ContentManagement.GraphQL.Queries.Types;
using OrchardCore.Modules;

namespace Lombiq.TrainingDemo.GraphQL;

/// <summary>
/// GraphQL启动配置 - 配置GraphQL相关的服务注册
/// 
/// 主要用途：
/// - 配置GraphQL相关的服务注册
 //* - 添加自定义内容部件的GraphQL支持
 //* - 注册GraphQL过滤器和构建器
 //* - 提供GraphQL schema的扩展机制
 //* 
 //* 使用场景：
/// - 为PersonPart添加GraphQL对象类型支持
/// - 注册GraphQL过滤器和构建器
/// - 配置索引别名提供程序
/// - 启用GraphQL功能模块
/// 
/// 设计原因：
/// - 提供模块化的GraphQL配置
/// - 支持自定义内容部件的GraphQL扩展
/// - 实现GraphQL功能的按需启用
/// - 提供统一的GraphQL服务注册机制
/// 
/// 设计模式：
/// - 启动模式：继承StartupBase实现模块启动
/// - 特性模式：使用RequireFeatures确保功能启用
/// - 服务注册模式：注册GraphQL相关服务
/// - 模块化模式：按模块组织GraphQL功能
/// </summary>
// Orchard Core的GraphQL模块为您提供了许多开箱即用的功能。内容类型、字段和一些内置部件会自动包含。
// 所以您只需要担心将自定义内容部件和过滤参数添加到GraphQL"schema"中。
// 警告：GraphQL将其属性称为"字段"。为了最小化与Orchard Core字段的混淆，我们在整个训练部分中专门将后者称为"内容字段"。
// 按照约定，GraphQL特定服务应放置在其模块的GraphQL目录中。不要忘记RequireFeatures属性：
// schema在单例作用域中启动时构建，所以当GraphQL被禁用时让它运行会很浪费。
// 当GraphQL功能启用时，您可以转到Configuration > GraphiQL来检查和尝试查询，而无需外部查询编辑器。
[RequireFeatures("OrchardCore.Apis.GraphQL")]
public sealed class Startup : StartupBase
{
    /// <summary>
    /// 配置服务方法 - 注册GraphQL相关的服务
    /// 
    /// 功能说明：
    /// - 注册PersonPart的GraphQL对象类型
    /// - 注册PersonPart的Where输入对象类型
    /// - 注册索引别名提供程序
    /// - 注册内容类型构建器和过滤器
    /// 
    /// 服务注册：
    /// - PersonPartObjectGraphType：人员部件对象类型
    /// - PersonPartWhereInputObjectGraphType：人员部件Where输入类型
    /// - PersonPartIndexAliasProvider：人员部件索引别名提供程序
    /// - ContentItemTypeBuilder：内容项类型构建器
    /// - PersonAgeGraphQLFilter：人员年龄GraphQL过滤器
    /// </summary>
    /// <param name="services">服务集合</param>
    public override void ConfigureServices(IServiceCollection services)
    {
        // 前3行将"person"字段添加到任何具有PersonPart的ContentItem类型字段。实现ObjectGraphType<TPart>来显示内容部件特定的字段。这是必需的。
        services.AddObjectGraphType<PersonPart, PersonPartObjectGraphType>();
        // 可选地，如果您有内容部件索引，实现WhereInputObjectGraphType<TPart>和PartIndexAliasProvider<TPartIndex>。
        // 这些将通过"where"参数为您提供数据库端过滤。
        services.AddInputObjectGraphType<PersonPart, PersonPartWhereInputObjectGraphType>();
        services.AddTransient<IIndexAliasProvider, PersonPartIndexAliasProvider>();

        // 有时您需要更高级的过滤逻辑或无法用YesSql查询表达的过滤。在这种情况下，
        // 您可以通过实现IContentTypeBuilder添加自定义过滤属性，然后在实现IGraphQLFilter<ContentItem>的类中评估它们的值。
        services.AddScoped<IContentTypeBuilder, ContentItemTypeBuilder>();
        services.AddTransient<IGraphQLFilter<ContentItem>, PersonAgeGraphQLFilter>();
    }
}

// 下一站：Services/PersonPartObjectGraphType.cs
